<!--
 * @Description: 
 * @Author: ldx
 * @Date: 2023-04-26 13:36:56
 * @LastEditors: ldx
 * @LastEditTime: 2023-04-26 15:16:42
-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #canvas{
      background: #000;
    }
  </style>
</head>
<body>
  <canvas id="canvas"></canvas>
  <script>
    const canvas = document.getElementById('canvas')
    //canvas充满窗口
    canvas.width=400;
    canvas.height=600;
    const ctx=canvas.getContext('2d');

    const data = {
      center:[0,0],
      c1:{
        startPoint:[-10.5,10],
        controlPoint:[0,25],
        endPoint:[10.5,10],
      },
      c2:{
        startPoint:[-10,-10],
        controlPoint:[0,-25],
        endPoint:[10,-10],
      }
    }

    // 获取路径上的等分点
    const getPoints = (data,type)=>{
      const [p1,p2,p3] = data
      const points = []
      if(type === 'QuadraticCurve'){
        const curvePath = getPathPointByQuadraticCurve(p1,p2,p3)
        for (let index = 0; index < 1; index+=0.1) {
          const point = curvePath(index)
          points.push(point)
        }
      }else{
        const curvePath = getPathPointByLine(p1,p2)
        for (let index = 0; index < 1; index+=0.1) {
          const point = curvePath(index)
          points.push(point)
        }
      }
      return points
    }
    
    // 转换坐标
    const convertXY = (point)=>{
      const halfW = canvas.width / 2
      const halfH = canvas.height / 2
      const [x,y] = point
      return [halfW + x, halfH - y]
    }
    // 绘制
    const draw = (path)=>{
      ctx.strokeStyle= '#fff'
      //线宽
      ctx.lineWidth=2;
      //直线
      ctx.beginPath();
      path.forEach((item,i)=>{
        const [x,y] = item
        const [cx,cy] = convertXY([x,y])
        if(i === 0){
           ctx.moveTo(cx,cy);
        }else{
          ctx.lineTo(cx,cy);
        }
      })
      ctx.closePath();
      ctx.stroke();
    }
    // 或者直线上的等距离点位
    function getPathPointByLine (p0, p1) {
      const [x0,y0] = p0;
      const [x1,y1] = p1;

      return function (t) {
        if (t < 0 || t > 1) {
          throw new RangeError('The value range of parameter "t" is [0,1]');
        }

        return [
          x0 + (x1 - x0) * t,
          y0 + (y1 - y0) * t
        ]
      }
    }
    // 获取二阶贝塞尔曲线上的等距离点位
    function getPathPointByQuadraticCurve (sp, cp, ep) {
      const [x0,y0] = sp;
      const [x1,y1] = cp;
      const [x2,y2] = ep;

      return function (t) {
        if (t < 0 || t > 1) {
          throw new RangeError('The value of parameter "t" is [0,1]');
        }
        return [
          Math.pow(1 - t, 2) * x0 + 2 * t * (1 - t) * x1 + Math.pow(t, 2) * x2,
          Math.pow(1 - t, 2) * y0 + 2 * t * (1 - t) * y1 + Math.pow(t, 2) * y2
        ]
      }
    }
    // 创建单位矩阵
    const createMatrix =() =>{
      let m = []
      m[0] = 1
      m[1] = 0
      m[2] = 0
      m[3] = 1
      m[4] = 0
      m[5] = 0
      return m
    }
    // 矩阵相乘
    const multiply =(m1, m2) =>{
      let m = []
      m[0] = m1[0] * m2[0] + m1[2] * m2[1] + m1[4] * 0
      m[2] = m1[0] * m2[2] + m1[2] * m2[3] + m1[4] * 0
      m[4] = m1[0] * m2[4] + m1[2] * m2[5] + m1[4] * 1
      m[1] = m1[1] * m2[0] + m1[3] * m2[1] + m1[5] * 0
      m[3] = m1[1] * m2[2] + m1[3] * m2[3] + m1[5] * 0
      m[5] = m1[1] * m2[4] + m1[3] * m2[5] + m1[5] * 1
      return m
    }
    // 缩放
    // v 是个二维向量，即一个数组 [scaleX, scaleY]，向量 v 是用于表示 x y 方向的伸缩程度
    function scale(m, v) { 
      return multiply([v[0], 0, 0, v[1], 0, 0], m)
    }
    const multiplyVector = (m,v)=>{
      const [x,y] = v
      return [
        m[0]*x+m[2]*y,
        m[1]*x+m[3]*y
      ]
    }

    const {c1,c2} = data
    const points = [
      ...getPoints([c1.startPoint,c1.controlPoint,c1.endPoint],'QuadraticCurve'),
      ...getPoints([c1.endPoint,c2.endPoint],'Line'),
      ...getPoints([c2.endPoint,c2.controlPoint,c2.startPoint],'QuadraticCurve'),
      ...getPoints([c2.startPoint,c1.startPoint],'Line')
    ]
    console.log('points',points);
    const getScalePoints = (ratio)=>{
      const matrix = createMatrix()
      const scaleM = scale(matrix, ratio)
      const nP = points.map(point=>{
        return multiplyVector(scaleM,point)
      })
      return nP
    }
    for (let i = 0; i < 9; i++) {
      if(i===0){
        const np = getScalePoints([1.5,1.5])
        draw(np)
        ctx.fillStyle= 'red'
        ctx.strokeStyle= '#000'
        ctx.lineWidth=0;
        ctx.fill();
        ctx.stroke();
        const np1 = getScalePoints([0.5,0.5])
        draw(np1)
        ctx.fillStyle= '#000'
        ctx.strokeStyle= '#000'
        ctx.fill();
         ctx.stroke();
      }
      const ratio = i*2+1
      const np = getScalePoints([ratio,ratio])
      draw(np)
    }
  </script>
</body>
</html>